/***********************************************************************************
Copy right:	    hqyj Tech.
Author:         jiaoyue
Date:           2023.07.01
Description:    http请求处理
***********************************************************************************/

#include <sys/types.h>
#include <sys/socket.h>
#include "custom_handle.h"


#include "./shm_msg/shmem.h"
#include "./shm_msg/msg_queue_peer.h"
#include "./cJSON/cJSON.h"

// //
// #include "shmem.h"
// #include "msg_queue_peer.h"
// #include "cJSON.h"
// //


#define KB 1024
#define HTML_SIZE (64 * KB)

// 普通的文本回复需要增加html头部
#define HTML_HEAD "Content-Type: text/html\r\n" \
                  "Connection: close\r\n"

// 登录
static int handle_login(int sock, const char *input)
{
    char reply_buf[HTML_SIZE] = {0};
    char *uname = strstr(input, "username=");
    uname += strlen("username=");
    char *p = strstr(input, "password");
    *(p - 1) = '\0';
    printf("username = %s\n", uname);

    char *passwd = p + strlen("password=");
    printf("passwd = %s\n", passwd);

    if (strcmp(uname, "admin") == 0 && strcmp(passwd, "admin") == 0)
    {
        sprintf(reply_buf, "<script>localStorage.setItem('usr_user_name', '%s');</script>", uname);
        strcat(reply_buf, "<script>window.location.href = '/index.html';</script>");
        send(sock, reply_buf, strlen(reply_buf), 0);
    }
    else
    {
        printf("web login failed\n");

        //"用户名或密码错误"提示，chrome浏览器直接输送utf-8字符流乱码，没有找到太好解决方案，先过渡
        char out[128] = {0xd3, 0xc3, 0xbb, 0xa7, 0xc3, 0xfb, 0xbb, 0xf2, 0xc3, 0xdc, 0xc2, 0xeb, 0xb4, 0xed, 0xce, 0xf3};
        sprintf(reply_buf, "<script charset='gb2312'>alert('%s');</script>", out);
        strcat(reply_buf, "<script>window.location.href = '/login.html';</script>");
        send(sock, reply_buf, strlen(reply_buf), 0);
    }

    return 0;
}

static int handle_add(int sock, const char *input)
{
    int number1, number2;

    // input必须是"data1=1data2=6"类似的格式，注意前端过来的字符串会有双引号
    sscanf(input, "\"data1=%ddata2=%d\"", &number1, &number2);
    printf("num1 = %d\n", number1);

    char reply_buf[HTML_SIZE] = {0};
    printf("num = %d\n", number1 * number2);
    sprintf(reply_buf, "%d", number1 * number2);
    send(sock, reply_buf, strlen(reply_buf), 0);

    return 0;
}

/**
 * @brief 处理自定义请求，在这里添加进程通信
 * @param input
 * @return
 */
//
union val_t
{ 
    int b_val;  //bool类型存储空间
    int i_val;   //整形值存储空间
    float f_val;  //浮点值存储空间
};

struct std_node
{
	int key;  //唯一键值
	int type;  //数据点类型
    int dev_type;  //数据点属于哪个设备，根据网关支持的设备自行定义
	union val_t old_val;  //变化上报后需要更新旧值
    union val_t new_val;  //从共享内存取出最新数据，放到new_val中
    int ret;  //默认为-1，采集成功后设置为0，采集失败再置-1
};
//共享内存
static int sharedMemory(int sock)
{

    struct shm_param para;
    if(shm_init(&para,"shm",256)<0)
    {
        printf("shm init err\n");
        return 0;
    }
    int *p=(int *)shm_getaddr(&para);
    
    struct std_node *q=(struct std_node *)(p+1);
    cJSON *root =cJSON_CreateObject();
    cJSON_AddItemToObject(root,"type",cJSON_CreateNumber(1));
    cJSON_AddItemToObject(root,"result",cJSON_CreateNumber(0));
    cJSON *data=cJSON_CreateArray();
    cJSON_AddItemToObject(root,"data",data);
    char buf[32]="";
    for(int i=0;i<*p;i++)
    {
        cJSON *i=cJSON_CreateObject();
        cJSON_AddItemToObject(i,"key",cJSON_CreateNumber(q->key));
        if(q->type==1)
        {
            sprintf(buf,"%d",q->new_val.b_val);
        }    
        else if(q->type==2)
        {
            sprintf(buf,"%d",q->new_val.b_val);
        }
        else if(q->type==3)
        {
            sprintf(buf,"%.2f",q->new_val.f_val);
            printf("%f\n",q->new_val.f_val);
        }
        cJSON_AddItemToObject(i,"val",cJSON_CreateString(buf));
        cJSON_AddItemToArray(data,i);
        q++;
    }
    char *reply_buf=cJSON_Print(root);
    send(sock, reply_buf,strlen(reply_buf), 0);
    free(reply_buf);
    cJSON_Delete(root);
    shmdt(p);
    return 0;
}
//消息队列
struct msgbuf
{
    long mtype;
    int key;
    char mdata[256];
};
//消息队列
void messageQueues(int sock, int key,char *val)
{
    int a,b;
    struct msgbuf msg;
    msg.key=key;
    strcpy(msg.mdata,val);
    if(key==105||key==106)
    {
        msg.mtype=2;
    }
    else if(key==303)
    {
        msg.mtype=0;

    }
    printf("%ld\n",msg.mtype);
    msg_queue_send("msg",&msg,sizeof(struct msgbuf),0);
}

int parse_and_process(int sock, const char *query_string, const char *input)
{
    // query_string不一定能用的到

    // 先处理登录操作
    if (strstr(input, "username=") && strstr(input, "password="))
    {
        return handle_login(sock, input);
    }
   
    else // 剩下的都是json请求，这个和协议有关了
    {
        // 构建要回复的JSON数据
        cJSON *root=cJSON_Parse(input);
        cJSON *type=cJSON_GetObjectItem(root,"type");
    
        // 发送HTTP响应给客户端
        if(type->valueint==1)
        {
            sharedMemory(sock);
        }
        else if(type->valueint==2)
        {
            cJSON *data=cJSON_GetObjectItem(root,"data");
            cJSON *key=cJSON_GetObjectItem(data,"key");
            cJSON *val=cJSON_GetObjectItem(data,"val");
            messageQueues(sock,key->valueint,val->valuestring);
        }
    }

    return 0;
}